/**
 * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "arch/asm_support.h"
#include "asm_defines.h"
#include "shorty_values.h"

// void InterpreterToCompiledCodeBridgeDyn(const BytecodeInstruction* insn, const Frame *iframe, const void* entrypoint, ManagedThread* thread)
.global InterpreterToCompiledCodeBridgeDyn
.type InterpreterToCompiledCodeBridgeDyn, %function
InterpreterToCompiledCodeBridgeDyn:
    CFI_STARTPROC
    CFI_DEF_CFA(sp, 0)
    push {r1, lr}
    CFI_ADJUST_CFA_OFFSET(8)
    CFI_REL_OFFSET(lr, 4)

    sub sp, sp, #12
    CFI_ADJUST_CFA_OFFSET(12)

    stm sp, {THREAD_REG, fp}
    CFI_REL_OFFSET(fp, 4)
    CFI_REL_OFFSET(THREAD_REG, 0)

    add fp, sp, #12
    CFI_DEF_CFA_REGISTER(fp)
    CFI_ADJUST_CFA_OFFSET(-12)

    mov THREAD_REG, r3
    mov r3, #INTERPRETER_TO_COMPILED_CODE_BRIDGE
    str r3, [sp, #8]
    push {r4, r5, r6, r7, r8}
    // sp must be 8 byte aligned
    CFI_REL_OFFSET(r8,  -((3 + 1) * 4))
    CFI_REL_OFFSET(r7,  -((3 + 2) * 4))
    CFI_REL_OFFSET(r6,  -((3 + 3) * 4))
    CFI_REL_OFFSET(r5,  -((3 + 4) * 4))
    CFI_REL_OFFSET(r4,  -((3 + 5) * 4))

    // setup regs as follow
    // r0 - acc, r1 - num args, r2-r3 - function object as int64_t
    // r4 - insn, r5 - iframe.vregs, r6, r7, r8 - temp, lr - entrypoint
    mov r4, r0
    add r5, r1, #FRAME_VREGS_OFFSET
    mov lr, r2
    ldr r0, [r1, #FRAME_ACC_OFFSET]

    ldrb r6, [r4], #1 // read opcode and advance insn_ptr

    // The file contains code which checks opcode and jumps
    // to the corresponding handler.
    // At the end each handler jumps to .Linvoke_from_bridge label.
    // The file is autogenerated from runtime/templates/bridge_dispatch.S.erb
    // Handlers are distinguished by format and located in the corresponding files with name:
    // handle_call_<format>.S
    // If you get a compilation error that there is no such file it seems
    // new call format was introduced and you have to implement the corresponding handler.
#include "bridge_dispatch_dyn_arm.S"

.Linvoke:
    blx lr

    // Signal handler of the sampling profiler use stack space below sp, 
    // so change it carefully only after registers restoration
    sub sp, fp, #32
    pop {r4, r5, r6, r7, r8, THREAD_REG, fp}
    CFI_RESTORE(r4)
    CFI_RESTORE(r5)
    CFI_RESTORE(r6)
    CFI_RESTORE(r7)
    CFI_RESTORE(r8)
    CFI_RESTORE(THREAD_REG)
    CFI_RESTORE(r11)
    CFI_DEF_CFA(sp, 12)
    ldr lr, [sp, #8]
    CFI_RESTORE(lr)
    add sp, sp, #12
    CFI_ADJUST_CFA_OFFSET(-12)
    bx lr
    CFI_ENDPROC



// void InvokeCompiledCodeWithArgArrayDyn(
//       const coretypes::TaggedValue* values,  x0
//       uint32_t num_args,                     x1
//       const Frame *iframe,                   x2
//       const Method*,                         x3
//       ManagedThread* thread)                 x4
.global InvokeCompiledCodeWithArgArrayDyn
.type InvokeCompiledCodeWithArgArrayDyn, %function
InvokeCompiledCodeWithArgArrayDyn:
    // TODO(audovichenko): Implement the function
    bx lr
